home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / piblist.lbr / FIND.PQS / find.pas
Pascal/Delphi Source File  |  1985-03-28  |  13KB  |  320 lines

  1. (*----------------------------------------------------------------------*)
  2. (*                  Find_Line --- Find line on file F                   *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Find_Line( n : REAL );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*   Procedure:   Find_Line                                             *)
  10. (*                                                                      *)
  11. (*   Purpose:     Finds and moves to specified line on file F           *)
  12. (*                                                                      *)
  13. (*   Calling sequence:                                                  *)
  14. (*                                                                      *)
  15. (*      Find_Line( n: REAL );                                           *)
  16. (*                                                                      *)
  17. (*         n --- line to be found                                       *)
  18. (*                                                                      *)
  19. (*   Calls:  Read_Line                                                  *)
  20. (*           RMIN                                                       *)
  21. (*           Clear_Buffer                                               *)
  22. (*           Skip_To_Line                                               *)
  23. (*           Reset_F                                                    *)
  24. (*           Scan_To_Eof                                                *)
  25. (*                                                                      *)
  26. (*   Remarks:                                                           *)
  27. (*                                                                      *)
  28. (*      On exit eod=TRUE if the line does not exist.  In this case the  *)
  29. (*      buffer is full and it contains the lines at end of the file.    *)
  30. (*      Otherwise eod=FALSE, line n is in the buffer, and top points    *)
  31. (*      to it.                                                          *)
  32. (*                                                                      *)
  33. (*      The algorithm divides into three cases.                         *)
  34. (*                                                                      *)
  35. (*      Case 1.  The line preceeds the buffer.  In this case the file   *)
  36. (*      is reset and the buffer is cleared.  The goal is to exit        *)
  37. (*      with the buffer full and with line n at the end of the buffer.  *)
  38. (*      This is accomplished by skipping the proper number of lines,    *)
  39. (*      then reading lines into the buffer until line n has been        *)
  40. (*      reached.                                                        *)
  41. (*                                                                      *)
  42. (*      Case 2.  The line is inside the buffer.  A simple linear search *)
  43. (*      of the buffer locates the requested line.                       *)
  44. (*                                                                      *)
  45. (*      Case 3.  The line follows the buffer.  This is the complicated  *)
  46. (*      case.  As in case 1, the goal is to exit with a full buffer     *)
  47. (*      and with line n at the end of the buffer.  However, if line n   *)
  48. (*      does not exist then we want to exit with a full buffer          *)
  49. (*      consisting of the lines at the end of the file.  For efficiency *)
  50. (*      in large forward skips, we don't want to simply read lines into *)
  51. (*      the buffer until line n or eof is encountered.  Skipping is     *)
  52. (*      faster than reading, so we'd prefer to skip lines, then read a  *)
  53. (*      full buffer's worth.  The problem is to determine how many      *)
  54. (*      lines to skip.                                                  *)
  55. (*                                                                      *)
  56. (*      (a) If line n is within Max_buf_lines of the last line in the   *)
  57. (*          buffer then no lines are skipped.  Lines are simply read    *)
  58. (*          into the buffer until line n or eof is reached.  This is    *)
  59. (*          a "short" forwards skip.                                    *)
  60. (*                                                                      *)
  61. (*      (b) Assume (a) doesn't hold.  If n is less than or equal to the *)
  62. (*          maximum line number seen so far then we know that line n    *)
  63. (*          must exist.  In this case we skip to line (n-Max_buf_lines),*)
  64. (*          then read lines into the buffer until line n is reached.    *)
  65. (*                                                                      *)
  66. (*      (c) Assume neither (a) nor (b) holds.  If we have earlier       *)
  67. (*          encountered eof on file f, then Max_line is the largest     *)
  68. (*          line number on the file, and we know whether or not line    *)
  69. (*          n exists.  In this case we skip to line min(n,Max_line) -   *)
  70. (*          Max_buf_lines, and then read lines into the buffer until    *)
  71. (*          either line n or eof is reached.                            *)
  72. (*                                                                      *)
  73. (*      (d) If none of cases (a), (b) or (c) hold then we scan to       *)
  74. (*          eof to determine whether or not line n exists.  Max_line    *)
  75. (*          is now the largest line number on the file.  File f is      *)
  76. (*          reset, and we proceed as in case (c).  Note that this case  *)
  77. (*          can occur at most once per run of PibList.                  *)
  78. (*                                                                      *)
  79. (*----------------------------------------------------------------------*)
  80.  
  81. VAR
  82.    m: REAL;
  83.  
  84. BEGIN  (* Find_Line *)
  85.  
  86.    eod := FALSE;
  87.                                    (* Case 1 *)
  88.    IF n < First^.lnum THEN
  89.       BEGIN
  90.  
  91.          Reset_F;
  92.  
  93.          Clear_Buffer;
  94.  
  95.          IF n > Max_buf_lines THEN Skip_To_Line( n - Max_buf_lines );
  96.  
  97.          REPEAT
  98.             Read_Line;
  99.          UNTIL last^.lnum = n;
  100.  
  101.          top := last
  102.  
  103.       END                          (* Case 2 *)
  104.    ELSE IF n <= last^.lnum THEN
  105.       BEGIN
  106.  
  107.          top := first;
  108.  
  109.          WHILE ( Top^.lnum < n ) DO top := Top^.next
  110.  
  111.       END
  112.    ELSE
  113.       BEGIN                        (* Case 3 *)
  114.  
  115.          IF ( NOT eof_seen ) AND ( ( n - Max_buf_lines ) > last^.lnum )
  116.             AND (n > Max_line) THEN
  117.                Scan_To_Eof;
  118.  
  119.          m := RMIN( n , Max_line ) - Max_buf_lines;
  120.  
  121.          IF m > last^.lnum THEN
  122.             BEGIN
  123.                Clear_Buffer;
  124.                Skip_To_Line( m )
  125.             END;
  126.  
  127.          REPEAT
  128.             Read_Line;
  129.          UNTIL ( last^.lnum = n ) OR EOF( F );
  130.  
  131.          top := last;
  132.          eod := Top^.lnum < n;
  133.  
  134.       END;
  135.  
  136. END   (* Find_Line *);
  137.  
  138. (*----------------------------------------------------------------------*)
  139. (*                  Find_Page --- Find first line of page on F          *)
  140. (*----------------------------------------------------------------------*)
  141.  
  142. PROCEDURE Find_Page( n : REAL );
  143.  
  144. (*----------------------------------------------------------------------*)
  145. (*                                                                      *)
  146. (*   Procedure:   Find_Page                                             *)
  147. (*                                                                      *)
  148. (*   Purpose:     Locates first line of page on file F.                 *)
  149. (*                                                                      *)
  150. (*   Calling sequence:                                                  *)
  151. (*                                                                      *)
  152. (*      Find_Page( n: REAL );                                           *)
  153. (*                                                                      *)
  154. (*         n --- Page to be found                                       *)
  155. (*                                                                      *)
  156. (*   Calls:  Read_Line                                                  *)
  157. (*           Skip_To_Page                                               *)
  158. (*           Scan_To_Eof                                                *)
  159. (*           Clear_Buffer                                               *)
  160. (*           Reset_F                                                    *)
  161. (*                                                                      *)
  162. (*   Remarks:                                                           *)
  163. (*                                                                      *)
  164. (*     On exit eod=TRUE if the page does not exist, in which case       *)
  165. (*     the buffer is full and it contains the Lines at the end of       *)
  166. (*     the file.                                                        *)
  167. (*                                                                      *)
  168. (*     Otherwise eod=FALSE, the first Line of page n is in the buffer,  *)
  169. (*     and top points to it.                                            *)
  170. (*                                                                      *)
  171. (*     The algorithm used by find_page is almost identical to that used *)
  172. (*     by find_line.                                                    *)
  173. (*                                                                      *)
  174. (*----------------------------------------------------------------------*)
  175.  
  176. VAR
  177.    before: BOOLEAN;
  178.    m:      REAL;
  179.  
  180. BEGIN  (* Find_Page *)
  181.  
  182.    eod := FALSE;
  183.  
  184.    before := ( n < First^.pnum ) OR
  185.       ( ( n = First^.pnum ) AND ( First^.Txt[1] <> eject_char ) );
  186.  
  187.    IF before THEN
  188.       BEGIN
  189.  
  190.          Reset_F;
  191.  
  192.          Clear_Buffer;
  193.  
  194.          IF n > Max_buf_pages THEN Skip_To_Page ( n - Max_buf_pages );
  195.  
  196.          REPEAT
  197.             Read_Line;
  198.          UNTIL last^.pnum = n;
  199.  
  200.          top := last
  201.  
  202.       END
  203.    ELSE IF n <= last^.pnum THEN
  204.       BEGIN
  205.  
  206.          top := first;
  207.  
  208.          WHILE ( Top^.pnum < n ) DO top := Top^.next
  209.  
  210.       END
  211.    ELSE
  212.       BEGIN
  213.  
  214.          IF ( NOT eof_seen ) AND ( ( n - Max_buf_pages ) > last^.pnum )
  215.             AND ( n > Max_page ) THEN
  216.                Scan_To_Eof;
  217.  
  218.          m := RMIN( n , Max_page ) - Max_buf_pages;
  219.  
  220.          IF m > last^.pnum THEN
  221.             BEGIN
  222.                Clear_Buffer;
  223.                Skip_To_Page( m )
  224.             END;
  225.  
  226.          REPEAT
  227.             Read_Line;
  228.          UNTIL ( last^.pnum = n ) OR EOF( F );
  229.  
  230.          top := last;
  231.          eod := Top^.pnum < n;
  232.  
  233.       END;
  234.  
  235. END   (* Find_Page *);
  236.  
  237. (*----------------------------------------------------------------------*)
  238. (*           Find_String --- Find next occurrence of string on F        *)
  239. (*----------------------------------------------------------------------*)
  240.  
  241. PROCEDURE Find_String( S: AnyStr );
  242.  
  243. (*----------------------------------------------------------------------*)
  244. (*                                                                      *)
  245. (*   Procedure:   Find_String                                           *)
  246. (*                                                                      *)
  247. (*   Purpose:     Find next occurrence of string on F                   *)
  248. (*                                                                      *)
  249. (*   Calling sequence:                                                  *)
  250. (*                                                                      *)
  251. (*      Find_String( S: AnyStr );                                       *)
  252. (*                                                                      *)
  253. (*         S --- String to be found                                     *)
  254. (*                                                                      *)
  255. (*   Calls:  Read_Line                                                  *)
  256. (*           Find_Line                                                  *)
  257. (*                                                                      *)
  258. (*----------------------------------------------------------------------*)
  259.  
  260. VAR
  261.    Found:  BOOLEAN;
  262.    Done:   BOOLEAN;
  263.    LineNo: INTEGER;
  264.    n:      INTEGER;
  265.  
  266. LABEL 1;
  267.  
  268. BEGIN  (* Find_String *)
  269.  
  270.    Found       := FALSE;
  271.    Done        := FALSE;
  272.  
  273.    Search_Lpos := 0;
  274.    Search_Col  := 0;
  275.  
  276.    REPEAT
  277.  
  278.       bot    := top;
  279.       LineNo := 0;
  280.       n      := Height;
  281.  
  282.       WHILE ( n > 0 ) AND ( NOT Eod ) DO
  283.          BEGIN
  284.  
  285.             LineNo := LineNo + 1;
  286.  
  287.             Search_Col := POS( Search_Str , Bot^.Txt );
  288.  
  289.             IF Search_Col <> 0 THEN
  290.                BEGIN
  291.                   Search_Lpos := LineNo;
  292.                   Search_Line := Bot^.Lnum;
  293.                   Found       := TRUE;
  294.                   GOTO 1;
  295.                END;
  296.  
  297.             n := n - 1;
  298.  
  299.             IF n > 0 THEN
  300.                IF bot = last THEN
  301.                   BEGIN
  302.                      Read_Line;
  303.                      Eod := eof(f);
  304.                      bot := last;
  305.                   END
  306.                ELSE
  307.                   bot := Bot^.next;
  308.  
  309.          END;
  310.  
  311.       Done := ( n > 0 );
  312.  
  313.       IF ( NOT Done ) THEN
  314.          Find_Line( Top^.lnum + Height );
  315.  
  316. 1:
  317.    UNTIL ( Found OR Done );
  318.  
  319. END    (* Find_String *);
  320.